package com.apollo.microService.DemoConsumer.Controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 在这里开发Eureka Client中的Application Client角色。就是consumer服务的消费者。
 * 服务消费者需要在注册中心中发现服务列表的。且同时将自己注册到注册中心的服务列表中。（参考如下截图）
 *
 * consumer在消费provider的时候，是通过LoadBalancer来实现的。
 * LoadBalancer简介 ： 是Eureka client内置的一个负载均衡器。复杂在发现的服务列表中选择服务应用，获取服务的IP和端口。
 * 实现服务的远程调用。
 *
 */
@RestController
public class DemoConsumerClientController {

    static String serviceId = "hello-world-service";

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * ribbon负载均衡器，其中记录了从Eureka Server中获取的所有服务信息。
     * 这些服务的信息是IP和端口等。应用名称，域名，主机名等信息。
     */
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    /**
     * 调用DiscoveryClient获取服务实例列表，取第一个服务实例
     * @return
     */
    @RequestMapping(value = "/discovery", method = RequestMethod.GET)
    public String discoveryHello() {
        ServiceInstance si = this.discoveryClient.getInstances(serviceId).get(0);
        return sayHello(si);
    }

    /**
     * 调用LoadBanlanceClient获取服务实例，choose策略见配置文件
     * @return
     */
    @RequestMapping(value = "/balance", method = RequestMethod.GET)
    public String balanceHello() {
        ServiceInstance si = this.loadBalancerClient.choose(serviceId);
        return sayHello(si);
    }

    private String sayHello(ServiceInstance si) {
        // 拼接访问服务的URL
        StringBuilder sb = new StringBuilder();
        sb.append("http://").append(si.getHost())
                .append(":").append(si.getPort()).append("/hello");

        System.out.println("本次访问的service是： " + sb.toString());

        // SpringMVC RestTemplate，用于快速发起REST请求的模板对象。
        /*
         * RestTemplate是SpringMVC提供的一个用于发起REST请求的模板对象。
         * 基于HTTP协议发起请求的。
         * 发起请求的方式是exchange。需要的参数是： URL, 请求方式， 请求头， 响应类型，【URL rest参数】。
         */
        RestTemplate rt = new RestTemplate();

        String info = rt.getForObject(sb.toString(), String.class);
        System.out.println(info);

        return info;
    }

}